use std::ptr;
use std::fmt::Debug;
use std::mem::size_of;
use crate::memory::{MemErrors, MemResult};


/// 指针对象 包含其指向对象的地址 以及指向的空间原始大小
#[derive(Clone, Debug)]
pub struct SizePointer {
    address: usize,
    type_size: usize,
}

/// 创建指针的玄妙方法组
impl SizePointer {
    /// 直接通过地址创建原始指针
    /// 该方法可算作直接创建了一个野指针 其指向内存不会被初始化
    /// # Safety
    /// 直接指向可能未知的内存区域是不安全的
    pub unsafe fn new_unknown(address: usize, type_size: usize) -> SizePointer {
        Self { address, type_size }
    }

    /// 通过类型实例创建指针\
    /// 一般此方法为推荐的指针创建方法
    pub fn from<T>(t: &T) -> SizePointer {
        let t_ptr = t as *const T;
        Self { address: t_ptr as usize, type_size: size_of::<T>() }
    }

    /// 直接通过地址创建原始指针
    /// 该方法会把实例覆盖给目标地址 有可能导致覆盖到其他数据
    /// # Safety
    /// 直接指向可能未知的内存区域是不安全的
    pub unsafe fn new_cover<T>(address: usize, t: T) -> SizePointer {
        let pointer = Self::new_unknown(address, size_of::<T>());
        pointer.cover_uncheck(t);
        pointer
    }
}

/// 基本方法
impl SizePointer {
    /// 获取类型占用内存大小
    pub fn type_size(&self) -> usize { self.type_size }

    /// 获取指针指向地址
    pub fn address(&self) -> usize { self.address }

    /// 是否可以转为目标类型
    pub fn is_enable_type<T>(&self) -> bool {
        size_of::<T>() == self.type_size
    }

    /// 获取指针指向的数据
    /// # Safety
    /// 未检查指向数据是否大小一致
    pub unsafe fn dereference_uncheck<T>(&self) -> T {
        ptr::read(self.address as *const T)
    }

    /// 获取指针指向的数据
    pub fn dereference<T>(&self) -> MemResult<T> {
        if !self.is_enable_type::<T>() { return Err(MemErrors::MemorySizeMismatching); }
        unsafe { self.dereference_uncheck() }
    }
}

impl SizePointer {
    /// 转为指针集合 按照数量分割大小与地址
    /// # Errors
    /// 如果内存不能对齐会返回错误
    pub fn to_ptr_arr(&self, num: usize) -> MemResult<Vec<SizePointer>> {
        if self.type_size % num != 0 {
            return Err(MemErrors::MemoryCannotAlignment);
        }
        let single_size = self.type_size / num;
        let mut vec = vec![];
        for i in 0..num {
            let ptr = unsafe {
                SizePointer::new_unknown(
                    self.address + i * single_size,
                    single_size,
                )
            };
            vec.push(ptr);
        }
        Ok(vec)
    }

    /// 将实例覆盖到当前指针指向
    /// # Safety
    /// 未检查实例与指向的大小是否一致
    pub unsafe fn cover_uncheck<T>(&self, src: T) {
        ptr::write(self.address as *mut T, src)
    }

    /// 将实例覆盖到当前指针指向
    /// # Errors
    /// 如果大小不一致会返回错误
    pub fn cover<T>(&self, src: T) -> MemResult<()> {
        if !self.is_enable_type::<T>() { return Err(MemErrors::MemorySizeMismatching); }
        unsafe { self.cover_uncheck(src) };
        Ok(())
    }

    /// 转换为原始指针
    /// # Errors
    /// 如果大小不匹配会返回错误
    pub fn to_const_ptr<T>(&self) -> MemResult<*const T> {
        if !self.is_enable_type::<T>() {
            Err(MemErrors::MemorySizeMismatching)
        } else {
            Ok(self.address as *const T)
        }
    }

    /// 转换为原始指针
    /// # Errors
    /// 如果大小不匹配会返回错误
    pub fn to_mut_ptr<T>(&self) -> MemResult<*mut T> {
        if !self.is_enable_type::<T>() {
            Err(MemErrors::MemorySizeMismatching)
        } else {
            Ok(self.address as *mut T)
        }
    }

    /// 指向下一个同等内存的区域
    /// # Safety
    /// 直接指向可能未知的内存区域是不安全的
    pub unsafe fn next(&self) -> Self {
        Self {
            address: self.address + self.type_size,
            type_size: self.type_size,
        }
    }

    /// 指向上一个同等内存的区域
    /// # Safety
    /// 直接指向可能未知的内存区域是不安全的
    pub unsafe fn prev(&self) -> Self {
        Self {
            address: self.address - self.type_size,
            type_size: self.type_size,
        }
    }
}

#[cfg(test)]
mod tests {}
